import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'compression_result.dart';
import 'light_compressor_ohos_platform_interface.dart';

enum VideoQuality {
  /// Very low quality
  very_low,

  /// Low quality
  low,

  /// Medium quality
  medium,

  /// High quality
  high,

  /// Very high quality
  very_high,
}

/// An implementation of [LightCompressorOhosPlatform] that uses method channels.
class MethodChannelLightCompressorOhos extends LightCompressorOhosPlatform {
  /// The method channel used to interact with the native platform.
  @visibleForTesting
  final methodChannel = const MethodChannel('light_compressor');

  /// A stream to listen to video compression progress
  static const EventChannel _progressStream =
  EventChannel('compression/stream');

  Stream<double>? _onProgressUpdated;

  /// Fires whenever the uploading progress changes.
  Stream<double> get onProgressUpdated {
    _onProgressUpdated ??= _progressStream
        .receiveBroadcastStream()
        .map<double>((dynamic result) => ((result ?? 0) as int).toDouble());
    return _onProgressUpdated!;
  }

  @override
  Stream<double> getUpdateStream() {
    return onProgressUpdated;
  }

  @override
  Future<String?> getPlatformVersion() async {
    final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }

  @override
  Future<String?> selectVideo() async {
    final path = await methodChannel.invokeMethod<String>('selectVideo');
    return path;
  }

  @override
  Future<bool?> cancelCompression() async {
    final result = await methodChannel.invokeMethod<bool>('cancelCompression');
    return result;
  }

  @override
  Future<double> getFileSize(String filePath) async {
    try {
      var size = (await methodChannel.invokeMethod<String>('getFileSize',<String,String>{
        'path':filePath
      }))!;
      return double.parse(size);
    }catch(e) {
      return 0;
    }
  }

  @override
  Future<Result> startCompression({
    required String path,
    required VideoQuality videoQuality,
  }) async {
    final Map<String, dynamic> response = jsonDecode((await methodChannel.invokeMethod<String>('startCompression',<String, dynamic>{
      'path': path,
      'videoQuality': videoQuality.toString().split('.').last
    }))!);
    if (response['onSuccess'] != null) {
      return OnSuccess(response['onSuccess']);
    } else if (response['onFailure'] != null) {
      return OnFailure(response['onFailure']);
    } else if (response['onCancelled'] != null) {
      return OnCancelled(isCancelled: response['onCancelled']);
    } else {
      return const OnFailure('Something went wrong');
    }
  }
}
